#pragma once

#include "Monitor.h"
#include "Object.h"
#include "Tools.h"

typedef enum _AppState AppState;
enum _AppState
{
        APP_STATE_INIT,         // 初始化
        APP_STATE_WAIT_NUMBER,  // 等待数字输入
        APP_STATE_WAIT_DECIMAL, // 等待小数位输入
        APP_STATE_WAIT_RECOVER, // 等待恢复
        APP_STATE_GET_OPERATOR, // 获取到运算符
        APP_STATE_GET_EQU,      // 获取到等于号
};

typedef enum _AppEvent AppEvent;
enum _AppEvent
{
        APP_EVENT_NUM_BTN = 1, // 数字 0 - 9 键
        APP_EVENT_DOT,         // 小数点
        APP_EVENT_OP,          // 运算符号
        APP_EVENT_CLEAN,       // 清空
        APP_EVENT_LEFT,        // 左移
        APP_EVENT_RIGHT,       // 右移
        APP_EVENT_EQU,         // 等于符号

        APP_EVENT_QUIT, // 测试：退出事件

        APP_EVENT_NONE = 0,
};

/**
 * Application 主应用对象
 * 主要用来管理数码管以及运算中的另一个数字，以及
 * 缓冲运算符号。具有 Application 主状态机，处理
 * 算术运算。
 *
 * monitor:
 * 代表第一个数字、数码管/数字一体对象
 *
 * num2:
 * 运算当中的另外一个数字
 *
 * state:
 * Application 状态机的状态
 *
 * event:
 * 根据按钮判断当前的按钮事件。
 *
 * button:
 * 关联外部按钮，通过 Tools 中的 button_type_get()
 * 获取当前的按钮类型。
 *
 * operate[2]:
 * 当前的运算符。按下运算符时，首先将 operate[1] 中
 * 的运算符移动到 operate[0] 当中，再将按下的运算符
 * 存储到 operate[1] 当中。而后通过运算符 operate[0]
 * 来判断该进行何种算术运算。
 */
OBJECT_DECLARE (Application, application)
#define APPLICATION(any_obj) ((Application*)(any_obj))
struct _Application
{
        Object     parent_instance;
        Monitor*   monitor;
        Number*    num2;
        AppState   state;
        AppEvent   event;
        ButtonType button;
        ButtonType operate[2];
};

/**
 * @brief 运行一个 Application 对象。
 *
 * @param obj 本对象
 */
void application_run (Application* obj);
